/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package facturacion.negocio;

import factura.modelo.ClavePrimaria;
import factura.util.Parametro;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.transaction.RollbackException;
import javax.transaction.UserTransaction;

/**
 *
 * @author Romig Sevilla
 * @version 1.0
 */
@Singleton()
@javax.ejb.ApplicationException(rollback = true)
@TransactionManagement(TransactionManagementType.BEAN)
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class ManejadorDB implements ManejadorDBRemote {

    @Resource
    private UserTransaction utx = null;
    @PersistenceUnit(unitName = "EAFacturacion-ejbPU")
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    @Override
    public <T extends ClavePrimaria> int insert(T entidad) {
        EntityManager em = null;
        int bandera = 0;


        try {
            Class instancia = Class.forName(entidad.getClass().getName());
            System.out.println("valor devuelto " + buscar(instancia, entidad.getId()));
            if ((buscar(instancia, entidad.getId())) == null) {

                utx.begin();
                em = getEntityManager();
                em.persist(entidad);
                utx.commit();

            } else {

                return 1;
            }
        } catch (RollbackException ex) {
            System.out.println("Exception " + ex);
            bandera = 2;

        } catch (Exception ex) {
            bandera = 3;
            System.out.println("Exception " + ex);
        } finally {
            if (em != null) {
                em.close();

            }

        }
        return bandera;

    }

    @Override
    public <T extends ClavePrimaria> T buscar(Class<T> entidad, Integer id) {
        EntityManager em = getEntityManager();
        Object objeto = null;
        if (id == null && entidad != null) {
            return (T) objeto;
        }

        objeto = em.find(entidad, id);

        em.close();
        return (T) objeto;
    }

    @Override
    public <T extends ClavePrimaria> List<T> buscarTodos(Class<T> objeto, String columna, boolean estatus, boolean ascendente) {

        final String entityName = objeto.getSimpleName();
        final Query query;
        EntityManager em = getEntityManager();

        if (ascendente) {
            query = em.createQuery("SELECT e from " + entityName + " e WHERE e.estatus = :estatus order by e." + columna + " asc").setParameter("estatus", estatus);

        } else {
            query = em.createQuery("SELECT e from " + entityName + " e WHERE e.estatus = :estatus order by e." + columna + " desc").setParameter("estatus", estatus);
        }
        final List<T> resultList = query.getResultList();
        if (em != null) {
            em.close();
        }
        return resultList;
    }

    public <T extends ClavePrimaria> List<T> busquedaPorFiltro(
            Class<T> entidad, String columna, boolean ascendente, boolean or, Parametro... params) {

        final String entityName = entidad.getSimpleName();
        StringBuffer sbQuery = new StringBuffer("SELECT e from ").append(entityName).append(" e");
        final Query query;

        Parametro[] params2 = null;


        boolean first = true;
        int i = 0;
        if (params != null && params.length > 0) {

            params2 = new Parametro[params.length];

            for (Parametro fP : params) {
                if (first) {
                    sbQuery.append(" where e.").append(fP.getCampo()).append(" like :").append("p" + i);
                } else {
                    sbQuery.append(or ? " or" : " and").append(" e.").append(fP.getCampo()).append(" like :").append("p" + i);
                }

                first = false;

                Parametro fPAux = new Parametro("p" + i, fP.getValor() + "%");
                params2[i] = fPAux;
                i++;
            }
        }
        System.out.println("Query " + sbQuery);
        if (ascendente) {
            sbQuery.append(" order by e." + columna + " asc");
        } else {
            sbQuery.append(" order by e." + columna + " desc");
        }

        query = createQuery(sbQuery.toString(), params2);

        final List<T> resultList = query.getResultList();

        return resultList;
    }

    private Query createQuery(String query, Parametro... params) {
        EntityManager em = getEntityManager();
        Query qQuery = em.createQuery(query);
        if (params != null && params.length > 0) {
            for (Parametro fP : params) {
                qQuery.setParameter(fP.getCampo(), fP.getValor());
            }
        }

        return qQuery;
    }

    @Override
    public <T extends ClavePrimaria> int modificar(T entidad) {
        EntityManager em = null;
        int bandera = 0;


        try {
            Class instancia = Class.forName(entidad.getClass().getName());
            if ((buscar(instancia, entidad.getId())) != null) {
                utx.begin();
                em = getEntityManager();
                em.merge(entidad);
                utx.commit();

            } else {

                bandera = 2;
            }

        } catch (RollbackException ex) {
            try {
                utx.rollback();
                bandera = 2;
                System.out.println("Exception " + ex);
            } catch (Exception ex1) {
                Logger.getLogger(ManejadorDB.class.getName()).log(Level.SEVERE, null, ex1);
            }

        } catch (Exception ex) {
            bandera = 3;
            System.out.println("Exception dddd " + ex);
        } finally {
            if (em != null) {
                em.close();
            }

        }
        return bandera;




    }

    @Override
    public Long obtenerSecuenId() {
        EntityManager em = getEntityManager();
        Long valorSecuencia=(Long) em.createNativeQuery("SELECT currval('facturacion.idfactura')").getSingleResult();
        em.close();
        return valorSecuencia;

    }
}
